/*
 * Copyright© 2003-2019 浙江汇信科技有限公司, All Rights Reserved.
 */
package com.icinfo.cloud.provider.punish.ucase.casemain.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.icinfo.cloud.provider.common.constant.Constant;
import com.icinfo.cloud.provider.common.enums.TerritoryCodeEnum;
import com.icinfo.cloud.provider.common.exception.BusinessException;
import com.icinfo.cloud.provider.common.utils.BaseUtil;
import com.icinfo.cloud.provider.common.utils.DateUtil;
import com.icinfo.cloud.provider.punish.ucase.casemain.dto.AppendixDto;
import com.icinfo.cloud.provider.punish.ucase.casemain.enums.CaseStatusEnum;
import com.icinfo.cloud.provider.punish.ucase.casemain.mapper.CaseAppendixRecordMapper;
import com.icinfo.cloud.provider.punish.ucase.casemain.mapper.CaseMainInfoMapper;
import com.icinfo.cloud.provider.punish.ucase.casemain.mapper.CaseMainInfoStatusChangeRecordHisMapper;
import com.icinfo.cloud.provider.punish.ucase.casemain.mapper.CaseMainInfoStatusChangeRecordMapper;
import com.icinfo.cloud.provider.punish.ucase.casemain.model.CaseAppendixRecord;
import com.icinfo.cloud.provider.punish.ucase.casemain.model.CaseMainInfo;
import com.icinfo.cloud.provider.punish.ucase.casemain.model.CaseMainInfoStatusChangeRecord;
import com.icinfo.cloud.provider.punish.ucase.casemain.model.CaseMainInfoStatusChangeRecordHis;
import com.icinfo.cloud.provider.punish.ucase.casemain.service.ICaseAppendixRecordService;
import com.icinfo.cloud.provider.punish.ucase.casemain.service.ICaseMainInfoService;
import com.icinfo.cloud.provider.punish.ucase.casemain.service.ICaseMainInfoStatusChangeRecordService;
import com.icinfo.cloud.provider.punish.ucase.casemain.vo.CaseMainInfoVo;
import com.icinfo.cloud.provider.punish.ucase.investigateevidence.dto.CaseOperateUpdateDto;
import com.icinfo.cloud.provider.punish.ucase.investigateevidence.dto.CaseStatusUpdateAfterApprovalDto;
import com.icinfo.cloud.provider.punish.ucase.investigateevidence.enums.CaseStatusChangeEffectEnum;
import com.icinfo.cloud.provider.punish.ucase.investigateevidence.enums.CaseStatusChangeTypeEnum;
import com.icinfo.framework.core.service.support.MyBatisServiceSupport;
import com.icinfo.framework.mybatis.mapper.entity.Example;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 描述: 案件暂停恢复记录表 case_main_info_status_change_record 对应的Service接口实现类.<br>
 *
 * @author framework generator
 * @date 2022年05月23日
 */
@Service
public class CaseMainInfoStatusChangeRecordServiceImpl extends MyBatisServiceSupport implements ICaseMainInfoStatusChangeRecordService {
    /**
     * 日志记录器
     */
    private static final Logger logger = LoggerFactory.getLogger(CaseMainInfoStatusChangeRecordServiceImpl.class);

    @Resource
    private CaseMainInfoStatusChangeRecordMapper caseMainInfoStatusChangeRecordMapper;
    @Resource
    private CaseMainInfoStatusChangeRecordHisMapper caseMainInfoStatusChangeRecordHisMapper;
    @Resource
    private CaseMainInfoMapper caseMainInfoMapper;
    @Resource
    private ICaseAppendixRecordService caseAppendixRecordService;
    @Resource
    private CaseAppendixRecordMapper caseAppendixRecordMapper;
    @Resource
    private ICaseMainInfoService caseMainInfoService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int saveCaseChangeOperate(CaseOperateUpdateDto updateDto) {
        CaseMainInfoStatusChangeRecord record = getCaseMainInfoStatusChangeRecordByChangeType(updateDto.getCaseId(), updateDto.getCaseOperateType());
        validCaseStatusChangeSaveParam(updateDto, record, updateDto.getCaseOperateType());
        //保存附件
        dealAppendix(updateDto);
        //更新案件状态变更表
        CaseMainInfoStatusChangeRecord changeRecord = new CaseMainInfoStatusChangeRecord();
        BeanUtils.copyProperties(updateDto, changeRecord);
        changeRecord.setCaseChangeType(updateDto.getCaseOperateType());
        changeRecord.setDocumentId(updateDto.getDocumentId());
        changeRecord.setCaseNumber(updateDto.getCaseNumber());
        if (ObjectUtil.isNotEmpty(updateDto.getDataMap().get(Constant.CASE_POSTPONE_DAY))) {
            changeRecord.setCasePostponeDay(Integer.valueOf(updateDto.getDataMap().get(Constant.CASE_POSTPONE_DAY).toString()));
        }
        if (ObjectUtil.isEmpty(record)) {
            changeRecord.setId(BaseUtil.createUid());
            changeRecord.setStatus(CaseStatusChangeEffectEnum.INVALID.getCode());
            changeRecord.setChangeSubmitTime(LocalDateTime.now());
            return caseMainInfoStatusChangeRecordMapper.insertSelective(changeRecord);
        } else {
            changeRecord.setId(record.getId());
            return caseMainInfoStatusChangeRecordMapper.updateByPrimaryKeySelective(changeRecord);
        }
    }

    /**
     * 描述：校验保存参数
     *
     * @param updateDto 更新dto
     * @param record    记录
     * @return {@link String }
     * @author shishengyao
     * @date 2022/07/14
     */
    private void validCaseStatusChangeSaveParam(CaseOperateUpdateDto updateDto, CaseMainInfoStatusChangeRecord record, String caseChangeType) {
        if (ObjectUtil.isNotEmpty(record)) {
          boolean flag= CaseStatusChangeEffectEnum.VALID.getCode().equals(record.getStatus());
            // 修改
            if (CaseStatusChangeTypeEnum.POSTPONE.getCode().equals(caseChangeType) && flag ) {
                throw new BusinessException("已延期成功，不可再次延期");
            }
            if (CaseStatusChangeTypeEnum.REVOKE.getCode().equals(caseChangeType) && flag) {
                throw new BusinessException("已延期成功，不可再次撤销");
            }
            if (CaseStatusChangeTypeEnum.TERMINATE.getCode().equals(caseChangeType) && flag) {
                throw new BusinessException("已延期成功，不可再次终止");
            }
//            if (!record.getDocumentId().equals(updateDto.getDocumentId())) {
//            }
            if (CaseStatusChangeTypeEnum.SUSPEND.getCode().equals(caseChangeType) && flag) {
                throw new BusinessException("案件在中止状态，请先恢复后再提交中止申请");
            }
        }
        Example example = new Example(CaseMainInfoStatusChangeRecord.class);
        example.createCriteria().andNotEqualTo("caseChangeType", caseChangeType)
                .andEqualTo("caseId", updateDto.getCaseId())
        .andEqualTo("status", CaseStatusChangeEffectEnum.INVALID.getCode());
        List<CaseMainInfoStatusChangeRecord> changeRecords = caseMainInfoStatusChangeRecordMapper.selectByExample(example);
     //   List<CaseMainInfoStatusChangeRecord> invalidOperate = changeRecords.stream().filter(e -> CaseStatusChangeEffectEnum.INVALID.getCode().equals(e.getStatus())).collect(Collectors.toList());
        if (ObjectUtil.isNotEmpty(changeRecords) && changeRecords.size() > 0) {
            String operateType = changeRecords.get(0).getCaseChangeType();
            throw new BusinessException("有在进行中的" + CaseStatusChangeTypeEnum.getValueByCode(operateType) + "操作，请先完成");
        }

        if (CaseStatusChangeTypeEnum.POSTPONE.getCode().equals(caseChangeType)) {
            Integer casePostponeDay = 0;
            if (ObjectUtil.isEmpty(updateDto.getDataMap().get(Constant.CASE_POSTPONE_DAY))) {
                throw new BusinessException("延期天数不能为空");
            } else {
                casePostponeDay = Integer.valueOf(updateDto.getDataMap().get(Constant.CASE_POSTPONE_DAY).toString());
                //判断是否为应急条线，应急条线最长为60天
                CaseMainInfo caseMainInfo = caseMainInfoMapper.selectByPrimaryKey(updateDto.getCaseId());
                if (TerritoryCodeEnum.YJGL.getCode().equals(caseMainInfo.getCaseTerritoryCode())) {
                    if (casePostponeDay <= 0 || casePostponeDay > 60) {
                        throw new BusinessException("延期天数必须大于0天，并且小于等于60天");
                    }
                } else {
                    if (casePostponeDay <= 0 || casePostponeDay > 90) {
                        throw new BusinessException("延期天数必须大于0天，并且小于等于90天");
                    }
                }
            }
        }
    }

    @Override
    public CaseMainInfoStatusChangeRecord getCaseMainInfoStatusChangeRecordByChangeType(String caseId, String caseChangeType) {
        Example example = new Example(CaseMainInfoStatusChangeRecord.class);
        example.createCriteria().andEqualTo("caseChangeType", caseChangeType)
                .andEqualTo("caseId", caseId).andNotEqualTo("status", "3");
        List<CaseMainInfoStatusChangeRecord> changeRecords = caseMainInfoStatusChangeRecordMapper.selectByExample(example);
        if (ObjectUtil.isNotEmpty(changeRecords) && changeRecords.size() > 0) {
            return changeRecords.get(0);
        }
        return null;
    }

    @Override
    public CaseMainInfoStatusChangeRecord getCaseMainInfoStatusChangeRecordByDocumentId(String caseId, String documentId) {
        Example example = new Example(CaseMainInfoStatusChangeRecord.class);
        example.createCriteria().andEqualTo("documentId", documentId)
                .andEqualTo("caseId", caseId);
        List<CaseMainInfoStatusChangeRecord> changeRecords = caseMainInfoStatusChangeRecordMapper.selectByExample(example);
        if (ObjectUtil.isNotEmpty(changeRecords) && changeRecords.size() > 0) {
            return changeRecords.get(0);
        }
        return null;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateCaseStatusAfterLastApproval(CaseStatusUpdateAfterApprovalDto updateDto) {
        CaseMainInfoStatusChangeRecord changeRecord = getCaseMainInfoStatusChangeRecordByChangeType(updateDto.getCaseId(), updateDto.getCaseOperateType());
        if (ObjectUtil.isNotEmpty(changeRecord)) {
            //查询主表信息
            CaseMainInfo caseMainInfo = caseMainInfoMapper.selectByPrimaryKey(updateDto.getCaseId());
            CaseStatusChangeTypeEnum operateTypeEnum = CaseStatusChangeTypeEnum.getEnumByCode(changeRecord.getCaseChangeType());
            CaseMainInfo updateCaseMainInfo = new CaseMainInfo();
            String caseStatus = caseMainInfo.getCaseStatus();
            CaseMainInfoStatusChangeRecord newChangeRecord = new CaseMainInfoStatusChangeRecord();

            switch (operateTypeEnum) {
                case POSTPONE:
                    updateCaseMainInfo.setCaseDeadline(caseMainInfo.getCaseDeadline() + changeRecord.getCasePostponeDay());
                    //主表信息变更
                    updateCaseMainInfo.setCaseTimelimit(caseMainInfo.getCaseTimelimit().plusDays(changeRecord.getCasePostponeDay()));
                    caseStatus = CaseStatusEnum.POSTPONE.getCode();
                    break;
                case SUSPEND:
                    caseStatus = CaseStatusEnum.SUSPEND.getCode();
                    break;
                case RENEW:
                    caseStatus = CaseStatusEnum.HANDLING_CASE.getCode();
                    break;
                case TERMINATE:
                    //终止时如果案件已暂停，先恢复
                    if (CaseStatusEnum.SUSPEND.getCode().equals(caseMainInfo.getCaseStatus())) {
                        recoverCase(updateDto.getCaseId());
                    }
                    caseStatus = CaseStatusEnum.TERMINATE.getCode();
                    updateCaseMainInfo.setCaseEndTime(LocalDateTime.now());
                    break;
                case REVOKE:
                    caseStatus = CaseStatusEnum.REVOKE.getCode();
                    updateCaseMainInfo.setCaseEndTime(LocalDateTime.now());
                    break;
                default:
                    throw new BusinessException("未定义的案件操作方式");
            }
            //更新案件操作表状态
            newChangeRecord.setId(changeRecord.getId());
            newChangeRecord.setStatus(CaseStatusChangeEffectEnum.VALID.getCode());
            newChangeRecord.setChangeEffectTime(LocalDateTime.now());
            caseMainInfoStatusChangeRecordMapper.updateByPrimaryKeySelective(newChangeRecord);
            //更新主表办案状态
            updateCaseMainInfo.setId(updateDto.getCaseId());
            updateCaseMainInfo.setCaseStatus(caseStatus);
            caseMainInfoMapper.updateByPrimaryKeySelective(updateCaseMainInfo);
        }
    }


    private void dealAppendix(CaseOperateUpdateDto updateDto) {
        if (ObjectUtil.isNotEmpty(updateDto.getAppendixList()) && updateDto.getAppendixList().size() > 0) {
            List<AppendixDto> list = updateDto.getAppendixList();
            CaseMainInfo caseMainInfo = caseMainInfoMapper.selectByPrimaryKey(updateDto.getCaseId());

            // 先删除
            Example example1 = new Example(CaseAppendixRecord.class);
            example1.createCriteria().andEqualTo("documentCatalogCode", updateDto.getDocumentCatalogCode())
                    .andEqualTo("caseStageCode", caseMainInfo.getCaseCurrentStageCode()).andEqualTo("caseId", updateDto.getCaseId());
            caseAppendixRecordMapper.deleteByExample(example1);
            for (int i = 0; i < list.size(); i++) {
                CaseAppendixRecord record = new CaseAppendixRecord();
                record.setCaseId(updateDto.getCaseId());
                record.setCaseStageCode(caseMainInfo.getCaseCurrentStageCode());
                record.setDocumentCatalogCode(updateDto.getDocumentCatalogCode());
                record.setCaseStageCode(caseMainInfo.getCaseCurrentStageCode());
                record.setCaseStageName(caseMainInfo.getCaseCurrentStageName());
                record.setAppendixUrl(list.get(i).getAppendixUrl());
                record.setAppendixTypeId(list.get(i).getAppendixTypeId());
                record.setAppendixName(list.get(i).getAppendixName());
                caseAppendixRecordService.saveCaseAppendixRecord(record);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = {Error.class, Exception.class})
    public int recoverCase(String caseId) {
        Example example = new Example(CaseMainInfoStatusChangeRecord.class);
        example.createCriteria().andEqualTo("caseId", caseId)
                .andEqualTo("caseChangeType", CaseStatusChangeTypeEnum.SUSPEND.getCode())
                .andEqualTo("status", CaseStatusChangeEffectEnum.VALID.getCode());
        example.orderBy("changeEffectTime").desc();
        List<CaseMainInfoStatusChangeRecord> recordList = caseMainInfoStatusChangeRecordMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(recordList)) {
            return 0;
        }
        CaseMainInfoStatusChangeRecord changeRecord = recordList.get(0);
        // 更新案件信息
        long days = DateUtil.calculatePastDays(changeRecord.getChangeEffectTime().toLocalDate());
        CaseMainInfo mainInfo = caseMainInfoMapper.selectByPrimaryKey(caseId);
        mainInfo.setCaseStatus(CaseStatusEnum.HANDLING_CASE.getCode());
        mainInfo.setCaseTimelimit(mainInfo.getCaseTimelimit().plusDays(days));
        int num = caseMainInfoMapper.updateByPrimaryKeySelective(mainInfo);
        // 添加案件恢复记录
        CaseMainInfoStatusChangeRecord record = new CaseMainInfoStatusChangeRecord();
        BeanUtils.copyProperties(changeRecord, record);
        record.setId(changeRecord.getId());
        record.setCaseId(caseId);
        record.setCaseNumber(mainInfo.getCaseNumber());
        record.setStatus(CaseStatusChangeEffectEnum.RENEW.getCode());
        record.setCaseRestoreTime(LocalDateTime.now());
        caseMainInfoStatusChangeRecordMapper.updateByPrimaryKeySelective(record);
        //清除记录，加入历史
        CaseMainInfoStatusChangeRecordHis recordHis = new CaseMainInfoStatusChangeRecordHis();
        BeanUtils.copyProperties(record, recordHis);
        recordHis.setHisAddTime(LocalDateTime.now());
        caseMainInfoStatusChangeRecordHisMapper.insert(recordHis);
        return caseMainInfoStatusChangeRecordMapper.deleteByPrimaryKey(changeRecord.getId());

    }

    @Override
    @Transactional(rollbackFor = {Error.class, Exception.class})
    public int deleteStatusChangeRecordByDocumentId(String documentId) {
        Example example = new Example(CaseMainInfoStatusChangeRecord.class);
        example.createCriteria().andEqualTo("documentId", documentId);
        List<CaseMainInfoStatusChangeRecord> changeRecords = caseMainInfoStatusChangeRecordMapper.selectByExample(example);
        if (ObjectUtil.isNotEmpty(changeRecords) && changeRecords.size() > 0) {
            CaseMainInfoStatusChangeRecord changeRecord = changeRecords.get(0);
            if (!CaseStatusChangeEffectEnum.INVALID.getCode().equals(changeRecord.getStatus())) {
                throw new BusinessException(CaseStatusChangeTypeEnum.getValueByCode(changeRecord.getCaseChangeType()) + "已经生效，不可删除");
            }
        }
        return caseMainInfoStatusChangeRecordMapper.deleteByExample(example);
    }

    @Override
    @Transactional(rollbackFor = {Error.class, Exception.class})
    public int saveCaseTerminateRecord(String caseId, String caseStatus) {
        String caseOperateType = CaseStatusChangeTypeEnum.TERMINATE.getCode();
        Example example = new Example(CaseMainInfoStatusChangeRecord.class);
        example.createCriteria().andEqualTo("caseId", caseId);
        List<CaseMainInfoStatusChangeRecord> changeRecords = caseMainInfoStatusChangeRecordMapper.selectByExample(example);
        List<CaseMainInfoStatusChangeRecord> invalidOperate = changeRecords.stream().filter(e -> CaseStatusChangeEffectEnum.INVALID.getCode().equals(e.getStatus())).collect(Collectors.toList());
        if (ObjectUtil.isNotEmpty(invalidOperate) && invalidOperate.size() > 0) {
            String operateType = invalidOperate.get(0).getCaseChangeType();
            throw new BusinessException("存在未完成的" + CaseStatusChangeTypeEnum.getValueByCode(operateType) + "操作，请先完成");
        }
        CaseMainInfoVo caseMainInfo = caseMainInfoService.getCaseMainInfo(caseId);
        //更新主表办案状态
        CaseMainInfo updateCaseMainInfo = new CaseMainInfo();
        updateCaseMainInfo.setId(caseId);
        updateCaseMainInfo.setCaseStatus(caseStatus);
        //终止时如果案件已暂停，先恢复
        if (CaseStatusEnum.SUSPEND.getCode().equals(caseMainInfo.getCaseStatus())) {
            recoverCase(caseId);
        }
        updateCaseMainInfo.setCaseEndTime(LocalDateTime.now());
        caseMainInfoMapper.updateByPrimaryKeySelective(updateCaseMainInfo);
        //新增案件状态变更记录表
        CaseMainInfoStatusChangeRecord changeRecord = new CaseMainInfoStatusChangeRecord();
        changeRecord.setCaseChangeType(caseOperateType);
        changeRecord.setCaseNumber(caseMainInfo.getCaseNumber());
        changeRecord.setId(BaseUtil.createUid());
        changeRecord.setStatus(CaseStatusChangeEffectEnum.VALID.getCode());
        changeRecord.setChangeSubmitTime(LocalDateTime.now());
        changeRecord.setCaseId(caseId);
        return caseMainInfoStatusChangeRecordMapper.insertSelective(changeRecord);
    }

    @Override
    @Transactional(rollbackFor = {Error.class, Exception.class})
    public int saveCaseSuspendRecord(String caseId) {
        String caseOperateType = CaseStatusChangeTypeEnum.SUSPEND.getCode();
        Example example = new Example(CaseMainInfoStatusChangeRecord.class);
        example.createCriteria().andEqualTo("caseId", caseId);
        List<CaseMainInfoStatusChangeRecord> changeRecords = caseMainInfoStatusChangeRecordMapper.selectByExample(example);
        List<CaseMainInfoStatusChangeRecord> invalidOperate = changeRecords.stream().filter(e -> caseOperateType.equals(e.getCaseChangeType())).collect(Collectors.toList());
        if (ObjectUtil.isNotEmpty(invalidOperate) && invalidOperate.size() > 0) {
            CaseMainInfoStatusChangeRecord invalidOperateRecord = invalidOperate.get(0);
            //清除记录，加入历史
            CaseMainInfoStatusChangeRecordHis recordHis = new CaseMainInfoStatusChangeRecordHis();
            BeanUtils.copyProperties(invalidOperateRecord, recordHis);
            recordHis.setHisAddTime(LocalDateTime.now());
            caseMainInfoStatusChangeRecordHisMapper.insert(recordHis);
            caseMainInfoStatusChangeRecordMapper.deleteByPrimaryKey(invalidOperateRecord.getId());
        }
        CaseMainInfoVo caseMainInfo = caseMainInfoService.getCaseMainInfo(caseId);
        //更新主表办案状态
        CaseMainInfo updateCaseMainInfo = new CaseMainInfo();
        updateCaseMainInfo.setId(caseId);
        updateCaseMainInfo.setCaseStatus(CaseStatusEnum.SUSPEND.getCode());
        caseMainInfoMapper.updateByPrimaryKeySelective(updateCaseMainInfo);
        //新增案件状态变更记录表
        CaseMainInfoStatusChangeRecord changeRecord = new CaseMainInfoStatusChangeRecord();
        changeRecord.setCaseChangeType(caseOperateType);
        changeRecord.setCaseNumber(caseMainInfo.getCaseNumber());
        changeRecord.setId(BaseUtil.createUid());
        changeRecord.setStatus(CaseStatusChangeEffectEnum.VALID.getCode());
        changeRecord.setChangeSubmitTime(LocalDateTime.now());
        changeRecord.setChangeEffectTime(LocalDateTime.now());
        changeRecord.setCaseId(caseId);
        return caseMainInfoStatusChangeRecordMapper.insertSelective(changeRecord);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void recallCaseMainInfoStatusChangeRecordByCaseLinkCode(String caseId, String caseLinkCode) {
        caseMainInfoStatusChangeRecordMapper.updateCaseMainInfoStatusChangeRecordByCaseLinkCode(caseId, caseLinkCode);

    }
}
